NLLLossGrad ================= 对 NLLLoss(Negative Log Likelihood Loss)算子的反向传播过程进行计算,得到输入 logits 的梯度。 该算子根据前向 NLLLoss 的 ``reduction_type``,对上游梯度进行对应方式的反向分发,仅在真实类别索引处产生非零梯度,其余位置梯度为 0。 .. math:: \frac{\partial L}{\partial x_{i,j}} = \begin{cases} - g_i \cdot w_{y_i}, & j = y_i,\ \text{reduction = none} \\ - g \cdot w_{y_i}, & j = y_i,\ \text{reduction = sum} \\ - g \cdot \dfrac{w_{y_i}}{\sum w}, & j = y_i,\ \text{reduction = mean} \\ 0, & j \neq y_i \end{cases} 其中: - :math:`g_i` 表示逐样本损失梯度 - :math:`g` 表示归约后的标量损失梯度 - :math:`y_i` 表示第 :math:`i` 个样本的真实类别索引 - :math:`w_{y_i}` 表示对应类别权重 输入: - **logits** - 前向输入 logits 地址,形状为 ``[batch, class_num]`` (仅用于尺寸信息)。 - **loss_grad** - 上游损失梯度地址: - ``reduction_type = 0 (none)`` 时,形状为 ``[batch]`` - ``reduction_type = 1 / 2 (sum / mean)`` 时,仅使用 ``loss_grad[0]`` - **labels** - 真实标签索引地址,形状为 ``[batch]``。 - **weight** - 类别权重数组地址,形状为 ``[class_num]``。 - **total_weight** - 权重和地址(仅 ``reduction_type = mean`` 时使用)。 - **batch** - batch 大小。 - **class_num** - 类别数量。 - **reduction_type** - 损失归约方式: - ``0``:Sum - ``1``:Mean - ``2``:None - **core_mask** - 核掩码(仅适用于共享存储版本)。 输出: - **logits_grad** - logits 的梯度输出地址,形状为 ``[batch, class_num]``。 支持平台: ``FT78NE`` ``MT7004`` .. note:: - FT78NE 仅支持 fp 类型 - MT7004 支持 hp, fp 类型 - 输出梯度在非真实类别位置恒为 0 - ``labels`` 中索引需满足 ``0 <= label < class_num`` **共享存储版本:** .. c:function:: void hp_nlllossgrad_s(half* logits, half* loss_grad, int* labels, half* weight, half* total_weight, half* logits_grad, int batch, int class_num, int reduction_type, int core_mask) .. c:function:: void fp_nlllossgrad_s(float* logits, float* loss_grad, int* labels, float* weight, float* total_weight, float* logits_grad, int batch, int class_num, int reduction_type, int core_mask) **C调用示例:** .. code-block:: c :linenos: :emphasize-lines: 18-19 //FT78NE示例 #include #include int main(int argc, char* argv[]) { float *logits = (float *)0xA0000000; // [batch, class_num] float *loss_grad = (float *)0xA0001000; // 上游梯度 int *labels = (int *)0xA0002000; // [batch] float *weight = (float *)0xA0003000; // [class_num] float *total_weight = (float *)0xA0004000; float *logits_grad = (float *)0xC0000000; int batch = 32; int class_num = 1000; int reduction_type = 1; // Mean int core_mask = 0xff; fp_nlllossgrad_s(logits, loss_grad, labels, weight, total_weight, logits_grad, batch, class_num, reduction_type, core_mask); return 0; } **私有存储版本:** .. c:function:: void hp_nlllossgrad_p(half* logits, half* loss_grad, int* labels, half* weight, half* total_weight, half* logits_grad, int batch, int class_num, int reduction_type) .. c:function:: void fp_nlllossgrad_p(float* logits, float* loss_grad, int* labels, float* weight, float* total_weight, float* logits_grad, int batch, int class_num, int reduction_type) **C调用示例:** .. code-block:: c :linenos: :emphasize-lines: 17-18 //FT78NE示例 #include #include int main(int argc, char* argv[]) { float *logits = (float *)0x10810000; // L2空间 float *loss_grad = (float *)0x10820000; int *labels = (int *)0x10830000; float *weight = (float *)0x10840000; float *total_weight = (float *)0x10850000; float *logits_grad = (float *)0x10860000; int batch = 32; int class_num = 1000; int reduction_type = 2; // None fp_nlllossgrad_p(logits, loss_grad, labels, weight, total_weight, logits_grad, batch, class_num, reduction_type); return 0; }